比特币于 2009 年诞生后,我们很快就迎来了所谓的「山寨币」时代。人们在比特币的基础上衍生出了诸多想法,并付诸实验,一时间涌现出成千上万种加密货币。一些新的加密货币活了下来,另一些很快消失在我们的视野中。其中最成功的莫过于以太坊了。为什么是以太坊?
在以太坊之前,每当有人推出新的区块链应用,就会有一种新的「山寨币」被创造出来以实现该应用。以太坊终结了这种繁琐的创新方式,通过引入一种通用编程模型让开发者可以在其上构建任意去中心化应用。有了以太坊,开发者得以卸下编写共识代码和构建点对点网络的负担,将更多宝贵时间投入到商业逻辑上。以太坊之于其它「山寨币」就像 iPhone 之于它的功能手机[1] 前辈,为我们开启了 dApp 的寒武纪大爆发。
回顾这段历史的时候,我们很容易理解以太坊之所以能发展成最有价值的区块链的原因 —— 在其它项目还在一次解决一个问题的时候,它就通过系统化的方法一举解决了成千上万个问题。而以太坊提供系统化解决方案的方法,是通过在一个不同的层级解决问题:不满足于回答如何构建下一个应用,而是要回答如何更方便的去构建接下来的一万个应用 —— 有没有比「一个应用一条链」更好的方法?这样一种对其它「山寨币」的降维打击[2],开启了属于以太坊的新时代。由于开发成本大幅降低,dApp 得以蓬勃发展。如今,几乎所有 dApp 都在以太坊上运行,这让以太坊成为加密货币的佼佼者。
常有人问:以太坊会是区块链的终极形态吗?还是说未来会出现一个新的区块链,其之于以太坊就像以太坊之于比特币一样?下一个时代会是什么样子?
以太坊的主要突破是由 EVM 和账户模型构成的通用编程模型(又称智能合约模型,在本文中可互换),在其上开发者可以实现各类应用逻辑。智能合约模型是一个中间层,将开发者与开发应用不需要关心的区块链底层细节隔绝开来,同时又为开发者提供极好的编程灵活性。以太坊所做的事情正是抽象,如维基百科上对抽象的定义[3] 所说:
从这个角度来看,以太坊就是比特币和所谓「山寨币」的抽象。抽象是系统演化的永恒主题,在历史上发生过很多次。在编程技术的早期阶段,我们只能写着汇编代码直接与机器打交道,后来人们创造出了高级编程语言和编译器,将我们从繁琐的机器细节中解放了出来,只需关注更重要的问题。起初,我们直接在自己的程序内管理硬件资源,后来我们构建了操作系统作为中间层,代理我们处理那些繁重的任务。再往后,我们又实现了硬件虚拟化,于是应用可以在云端运行。早期的互联网只有少数几层协议,如 TCP/IP,后来发展出应用层,于是有了 HTTP、FTP 和 SMTP 等。如你所见,抽象的例子比比皆是。
因此,我想说的是,新的抽象是演化的标志,下一代区块链必须比上一代更加抽象。从比特币到以太坊的跨越是初代区块链抽象,同时我相信抽象的进程不会就此终止。如果想要知道后以太坊时代会是什么样子,我们首先应该思考的是,还可以从以太坊中进一步抽象掉什么。
与比特币相比,以太坊的通用智能合约模型是一大进步。若要再进一步抽象,一个方向是基于以太坊智能合约模型创建一个更抽象的模型。如果我们更深入探究以太坊模型,我们会发现该模型融入了很多特定的设计选择,其中比较主要的有:
- 账户地址。用户需要通过 EOA(外部账户)来发起交易。EOA 地址是公钥的 Keccak256 (一个特定的哈希算法)哈希值。
- 发送方身份验证。以太坊使用 Secp256k1 和 Keccak256 这两种特定的密码学算法对交易发送方进行身份认证。要想创建一笔有效的以太坊交易,客户端(如钱包)必须实现 Secp256k1 和 Keccak256 算法以签署该交易。这也导致客户端需要一种安全的方法来管理 Secp256k1 密钥对。
- 密码学原语(作为基础组件使用的一类算法)。为了给开发者提供便利,一些事先选择好的特定密码学原语被硬编码到 EVM(以太坊虚拟机)中作为预编译合约,例如,ECDSA 签名验证和 SHA256 哈希函数。同样的算法,被硬编码到 EVM 中比利用 Solidity 实现要高效得多,前者因此获得实用性。
- 世界状态结构。以太坊的世界状态是一个巨大的 Merkle Patricia Tree (MPT),账户就是叶节点。其中每个账户也以 MPT 的形式维护一个自己内部的键值数据库。MPT 是众多可验证数据结构的选项之一。
对于非技术背景的用户来说,这些设计选择看上去不明所以,但是其重要性不亚于共识算法或经济模型参数的选择。这些选择影响着以太坊的方方面面,就好像对普朗克常数[4] 进行微调也会给我们的宇宙带来翻天覆地的变化[5]。构建一个新的去中心化生态就像是创建一个新的宇宙,而这些设计选择就像是这个宇宙中设定好的物理规律。
当时有这些设计选择是为了帮助以太坊实现其初始目标,事后看来它们并非最佳选择。例如,发送方身份验证算法 Secp256k1 对设计者来说可能就是顺手一选,但是在不支持 secp256k1 的环境中[6] 它带来了不必要的障碍;通过一份小小的白名单内嵌预编译合约的做法,使得大部分广泛使用中的密码学原语被排除在应用之外;状态数据结构中使用的 MPT 也被证明是效率非常低下[7] 的,不仅加剧[8] 了状态爆炸问题,还导致了与 IO 相关的 EVM 操作码[9] 的定价困难,而定价不当可能会引发 DoS 攻击等安全问题。以太坊社区和其它一些新型协议也注意到了这些问题,并尝试了不同的解决方案。例如,以太坊通过一系列硬分叉来增加更多有用的预编译合约,并对操作码重新定价;Tezos 增加了 Secp256r1 作为新的发送方身份验证算法,等等。问题在于,这与人们当时在「山寨币」时代解决应用需求的方式毫无区别。更麻烦的是,这些设计选择可能比应用程序更加复杂和难以理解,而且通常不存在最佳解决方案。面对不同的情况,可能会有不同的最优解。即使遇到极少数存在一般最优解的情况,我们也无法保证当下的最佳选择在将来还是如此。因此,更好的方式是,我们再次从新的层面去思考:与其继续通过需要核心团队协调的硬分叉来增加新功能,我们是否可以创建新的抽象并给予智能合约开发者充分的自由?Nervos CKB 回答了这个问题,并创建了新抽象的层级。例如,CKB 交易是抽象的,因为用户和开发者不仅限于使用默认的 Blake2b-Secp256k1 验证算法,任何人都能将其替换成[10] 诸如 Blake2b-Secp256r1、Keccak256-ED25519 或 Blake2b-SHA3-Schnorr 的其他方式;CKB-VM 是抽象的,里面不包含任何预编译合约,即使是像哈希函数 Blake2b 和签名验证算法 Secp256k1 这样的默认密码学原语也只是在虚拟机中运行的智能合约,换言之,这些密码学原语与应用开发者创建的智能合约在同一个环境中运行,没有任何特权;Cell 模型是抽象的,其中每个 Cell 只是单纯的数据存储空间,没有任何内部结构,其布局完全取决于开发者,就像我们在 sUDT[11] 和 xUDT[12] 看到的那样。由于 CKB 在很多方面都是抽象的,开发者被赋予了更多的自由和新能力。CKB 是以太坊的抽象,正如以太坊是比特币的抽象那样。抽象让 CKB 成为了简单却又强大的区块链,并将很多工作转移到了链下(包括 Layer 2)。以太坊对比特币进行抽象的结果是将开发者分成了两部分:一部分是聚焦于底层区块链的区块链开发者,另一部分是构建应用的智能合约开发者。可以预见 CKB 对以太坊进行抽象也会将智能合约开发者分成系统合约开发者和应用合约开发者,前者聚焦于系统级智能合约,如密码学原语、lock script,甚至是内存管理模块。
最近以太坊社区已经认识到了区块链抽象的重要性并提出了一些相关的改进[13]。如果这些改进得以实现,我认为它会让以太坊变得比现在更加抽象,并与其它做不到这一点的项目拉开更大的距离。然而我不认为这些关于区块链抽象的提案能让以太坊达到与 CKB 同等的抽象层级,因为要对一个正在运行的生态系统做如此底层的改变是极其困难的,就像我们无法在不破坏宇宙的情况下改变普朗克常数那样。例如,账户抽象会为交易池等重要模块引入新的安全复杂性——此时每当签署新的交易时,验证节点都需要处理任意计算,而非固定的签名验证。
抽象也可以从可扩展性入手。分片和 Layer 2 解决方案都存在同样的问题,即,在某些方面改变了应用的开发方式。例如,跨分片调用[14] 或跨 Layer 2 交易在处理方式上可能与 Layer 1 上的合约调用完全不同。Layer 2 应用开发者还可能会在不同分层上遇到不同的智能合约模型(例如,Layer 1 采用的是账户模型,Layer 2 却采用 UTXO 模型,或者相反)。我们该如何屏蔽这些细节,为应用开发者提供无异于 Layer 1 的流畅开发体验?这个问题尚无定论,这是我们正在积极挑战的问题之一。
每一个区块链抽象层级都会给我们带来新的东西,我们在之前的抽象层级上从未见过的东西。第一次区块链抽象为我们带来了通用可编程性和互相连接的去中心化应用。下一次区块链抽象将为我们带来什么?
互操作性 2.0(我在 2020 年万向区块链大会上首次提到这个概念)必将是新抽象层级孕育的果实之一。我们对数字经济未来的设想是,公有链、许可链和中心化系统都将并存。有了互操作性,我们就可以在彼此独立的系统之间转移资产并调用智能合约。近年来,人们已经进行[15] 了很多关于互操作性[16] 的研究[17]和尝试[18] ,并且相信该问题可以通过一系列互操作基础原语解决,例如多签公证、中继和哈希锁定。
虽然区块链互操作性目前在技术上是可行的,但是与具备无缝互操作性的数字经济之间还存在缺失环节。第一,目前的互操作性尝试只会导致更加严重的网络分裂。Polkadot[19] 和 Cosmos[20] 等项目都定义了自己的标准,并试图围绕自己的「交换链(Hub)」建立一个多链网络。此外还有努力搭建直接桥梁的项目,例如实现比特币和以太坊之间的直接跨链。我们很难想象,这些独立网络的核心团队和社区有朝一日能够坐下来共同商定出一个所有人都遵守的互操作性标准。第二,更重要的是,即使这些区块链网络之间具备完美的技术互操作性,用户依然会被糟糕的互操作体验劝退。从用户的角度来看,如果我是一名比特币用户,想要将我的比特币转移到以太坊上参与 DeFi 应用,我必须先运行我的比特币钱包,发起一笔跨链交易,然后使用另外一个以太坊钱包。为了完成一次跨链操作,我必须安装两个钱包应用,保管两组助记词,使用两个地址。这个过程本身非常复杂,而且仅适用于两条区块链的情况。如果用户想要与更多区块链交互,必须管理更多助记词/地址/密钥对。用户体验问题不仅阻碍了 dApp 的广泛落地,还破坏了去中心化——区块链的核心价值——因为用户不得不且一定会选择中心化服务来避免所有这些麻烦。
为解决上述两个问题,我们需要一种新的互操作性,我们管它叫互操作性 2.0。具备这种新型互操作性的区块链就像是一个「万维交换港」,可以在无需对方知觉的情况下实现与其它区块链的互操作。想要做到这一点,「万维交换港」就必须要能理解并执行其它区块链的协议,而非创建自己的协议并要求其它链来学习。它就好比是一个「语言通」,能主动学习并会说其他人的语言,这样就能与使用不同语言的人交流,其他人也更愿意与他交流。在加密货币世界中,所有协议(即,区块链使用的语言)都由密码学技术构建。这也意味着「万维交换港」必须广泛支持各种密码学原语,无论其是在现在还是将来的区块链中被使用到。另外,「万维交换港」还要能理解各种钱包所签署的交易,让用户使用任意一个钱包(只需要一个钱包)都能够使用这个「万维交换港」上运行的一切应用。互操作性 2.0 的这些需求恰好可以通过上面说的新抽象,密码学原语和身份验证来满足。这就是为什么以太坊用户可以使用 MetaMask 钱包操控 Nervos CKB 上的资产和 dApp[21] 而无需进行任何手动设置,甚至不会意识到自己正在使用 Nervos 应用。不仅是以太坊用户,EOS、Tron 以及其他区块链的用户也可以在 Nervos CKB 上操控资产或 dApp[22]。如果当前的支持列表中没有你喜欢的区块链,不用担心,你自己就可以通过创建并部署智能合约(或等待/雇佣智能合约开发者帮你做这件事)来添加支持。这一切都可以通过编写智能合约来完成,无需请求核心开发团队和/或实行硬分叉。
在 Nervos 上运行的应用可以免费获得互操作性 2.0 带来的好处。每一个 Nervos 应用都可以被所有的区块链用户群体访问到,我们将这种应用称为万维应用(Universal Application)。你可能会感觉自己在使用以太坊或 EOS 上的 dApp,而实际上底层管道和基础设施都是 Nervos 提供的。我相信这才是生活应该有的样子,就像一位互联网用户在访问网站时才不会关心这个网站是用 PHP 还是 JAVA 编写的,使用的是 MySQL 还是 PostgreSQL。用户根本不关心这些,而这才是对的。身为开发者,我们有责任创建抽象,向用户隐藏实现细节,这样我们就可以持续的用更好的软件来取代已有的实现,从而不断提供更好的用户体验。互操作性 2.0 可以将加密货币世界变得像如今的互联网这样,而这需要通过新的区块链抽象来实现。
更妙的是,除了区块链用户之外,万维应用甚至可以触及一个远比区块链用户更大的群体。加密货币世界依然是个很小的圈子,我们可以「破圈」而出。区块链钱包和账户只不过是另一个账户/身份系统,而互联网世界早已确立了多种身份/账户体系和验证标准,如 OpenID、人脸识别和指纹识别等。通过密码学原语和身份验证抽象,Nervos CKB 同样可以理解广泛使用的互联网协议。这样一来,用户就能使用浏览器和手机来访问万维应用,无需安装任何区块链钱包,无需生成密钥对,甚至无需保管任何助记词。通过这种方式,我们可以主动适应现有的互联网生态,而非创建一个全新的生态。我们的爷爷奶奶不需要费力去学习一些看起来像是魔法的东西就能享受到技术带来的便利。阻碍互联网用户进入加密货币世界的壁垒在这里不再存在。
许多现代大都市都是从贸易枢纽或港口发展而来的。威尼斯、纽约、香港、上海和新加坡都是凭借自身的港口优势而成为高度商业化的城市。在工业时代,我们利用 GPS、货船和集装箱这样的互操作技术在不同城市之间转移资产。如今,我们有了加密资产、区块链和互操作性 2.0。更好的互操作性会为城市带来更多移民、贸易和活力。高楼将会耸立,货物川流不息,资产在此栖息,人们在此聚集,一座新的大都市从此诞生。
[1]https://en.wikipedia.org/wiki/Feature_phone[2]https://en.wikipedia.org/wiki/Death%27s_End
[3]https://en.wikipedia.org/wiki/Abstraction_(computer_science)[4]https://en.wikipedia.org/wiki/Planck_constant[5]https://iopscience.iop.org/article/10.1088/0143-0807/37/5/055406/meta[6]https://crypto.stackexchange.com/questions/85831/what-ec-curve-is-used-by-apple-ios-platform[7]https://hackernoon.com/getting-deep-into-geth-why-syncing-ethereum-node-is-slow-1edb04f9dc5
[8]https://blog.ethereum.org/2021/03/03/geth-v1-10-0/[9]https://eips.ethereum.org/EIPS/eip-1884[10]https://talk.nervos.org/t/lay2-pw-sdk-build-dapps-on-ckb-and-run-them-everywhere/4289[11]https://talk.nervos.org/t/rfc-simple-udt-draft-spec/4333[12]https://talk.nervos.org/t/rfc-extensible-udt/5337[13]https://hackmd.io/@SamWilsn/ryhxoGp4D[14]https://ethresear.ch/t/cross-shard-defi-composability/6268[15]https://docs.zkproof.org/pages/standards/accepted-workshop3/proposal-plumo_celolightclient.pdf[16]https://docs.keep.network/tbtc/index.pdf[17]https://www.r3.com/wp-content/uploads/2017/06/chain_interoperability_r3.pdf[18]https://www.weforum.org/whitepapers/inclusive-deployment-of-blockchain-for-supply-chains-part-6-a-framework-for-blockchain-interoperability[19]https://polkadot.network/[20]https://cosmos.network/
[21]https://talk.nervos.org/t/2-0-nervos-unidapp-dapp/5332[22]https://pay.lay2.dev/#/